/*
 * File: hybrid.js
 * Author: insane (luojie@doctorwork.com)
 * Last: insane (luojie@doctorwork.com>)
 * Date: 2018-04-Fr 03:16:45
 * Copyright 2018 - 2018 © Doctorwork
 */
import events from './events';

export const isHybrid = navigator ? /Hybrid/.test(navigator.userAgent) : false;
export const env = {
    Android: navigator ? /Android/.test(navigator.userAgent) : false
};
/**
 * 全局的Hybrid 对象，主要管理callback
 */

const Hybrid = {
    handlers: {},
    callback({ data, callback }) {
        console.log('Hybrid callback', window.Hybrid.handlers);
        window.Hybrid.handlers[callback](data);
    },
    on(callback, watcher) {
        console.log('Hybrid on');
        window.Hybrid.handlers[callback] = watcher;
    },
    event(type) {
        console.log('Hybrid event');
        events.fire(type);
    }
};
if (window) {
    window.Hybrid = Hybrid;
}
/**
 * 支持的hybrid协议,
 * TODO: 后续需要根据实际客户端版本进行协议调用限制
 */
const protocols = [
    'pay',
    'forward',
    'upload',
    'header',
    'init',
    'location',
    'loading',
    'modal',
    'back',
    'scroll',
    'pageshow',
    'pagehide',
    'device',
    'fetch',
    'clipboard',
    'permissions',
    'heathSet',
    'loginOut',
    'dismiss',
    'selectHeathData',
    'share',
    'storage',
    'statusBar',
    'shareWeapp',
    'saveImage',
    'userInfor'
];
/**
 *
 * @param name 协议名称
 * @param cb 实际的回调方法
 */
function setupCallback(name, cb) {
    Hybrid.on(name, function() {
        cb && cb();
    });
    return name;
}
/**
 * header 协议的 left/right 中 callback 配置
 * left: [{callback: () =>{}}]
 * @param name 名称
 */
function headerMapper(name) {
    return function _mapIteration(item, index) {
        item.callback = setupCallback(name + index, item.callback);
        return item;
    };
}
const mappers = {
    location({ params, callback }) {
        const time = new Date().getTime();
        let newParams = {};
        Object.keys(params).map(action => {
            if (typeof params[action] === 'function') {
                const name = `hybrid_callback_location_${action}_${time}`;
                setupCallback(name, params[action]);
                newParams[action] = name;
            } else if (['timeout', 'precision'].indexOf(action)) {
                newParams[action] = params[action];
            }
        });
        return { params: newParams, callback };
    },
    header(opts) {
        const { left, right } = opts.params;
        if (left) {
            opts.params.left = left.map(headerMapper('header_left'));
        }
        if (right) {
            opts.params.right = right.map(headerMapper('header_right'));
        }
        return opts;
    }
};
/**
 * 底层协议实现
 * @param {*string} command 协议名称
 * @param {*object} opts 协议参数
 */
function invoke(command, opts = {}) {
    if (mappers[command]) {
        opts = mappers[command](opts);
    }
    let params = Object.assign({ name: command }, opts);
    if (env.Android) {
        window.requestHybrid.postMessage(JSON.stringify(params));
    } else {
        window.webkit.messageHandlers.requestHybrid.postMessage(params);
    }
}
let increment = 1;
const _hybrid = function(action, opts = {}, callback = function() {}) {
    // 检查 action 是否可用
    if (!~protocols.indexOf(action)) {
        throw `protocol ${action} not supported`;
    }
    if (!isHybrid) {
        return;
    }
    const time = new Date().getTime();
    const event = `hybrid_callback_${action}_${time}_${increment++}`;
    Hybrid.on(event, callback);

    invoke(action, { params: opts, callback: event });
};
export default _hybrid;
/**
 * hybrid 数据请求方法
 * @param method 请求方式
 * @param url 请求路径
 * @param data 请求参数
 * @param options 请求options
 */

// export const request = function (method, url, data, options) {
export const request = options => {
    console.log('hybrid request');
    return new Promise(resolve => {
        let body =
            options.method == 'POST' ? JSON.parse(options.data) : options.data;
        const params = Object.assign(
            {
                url: options.url,
                body: body,
                method: options.method,
                headers: options.headers
            },
            options
        );
        _hybrid('fetch', params, res => {
            const byBridRes = {
                statusCode: res.status,
                data: JSON.parse(res.data)
            };
            console.log('hybrid result ----', byBridRes);
            resolve(byBridRes);
        });
        _hybrid('loading', {
            name: 'end'
        });
    });
};

export const scrollControl = options => {
    _hybrid('scroll', options);
};

export const shareWeaApp = options => {
    _hybrid('shareWeapp', options);
};

/**
 * 页面重新恢复到窗口
 * @param {*} callback
 */
export const pageShow = callback => {
    _hybrid('pageshow', {}, function() {
        callback();
    });
};
/**
 * 页面重新恢复到窗口
 * @param {*} callback
 */
export const pageHide = callback => {
    _hybrid('pagehide', {}, function() {
        callback();
    });
};
/**
 * 利用hybrid的存储
 * @param {*} type  只能是get , set , remove
 * @param {*} options 选项 { action : "set/get" , hash : "{name : 12}"}
 * @param {*} callback 回调
 */
export const storage = (options, callback) => {
    // 1. 转换成字符串存储
    if (typeof options.hash == 'object') {
        for (let key in options.hash) {
            options.hash[key] = JSON.stringify(options.hash[key]);
        }
    }
    if (options.action == 'get') {
        console.log('<<<<<  hybrid get 开始处理storage', options.hash);
    } else {
        console.log('>>>>> hybrid set 开始处理storage', options.hash);
    }
    _hybrid('storage', options, function(res) {
        // 2. 解析为对象
        try {
            for (let k in res) {
                res[k] = JSON.parse(res[k]);
            }
            console.log('《《《《  hybrid get 开始处理storage', res);
        } catch (e) {}
        // 3. 判断是否需要向下解析(这里默认会拿到所有存储的数据)
        if (options.action == 'get' && options.hash) {
            callback(res[options.hash]);
        } else {
            callback(res);
        }
    });
};

/**
 * 保存图片
 * @param {string} options 图片地址
 */
export const saveImage = options => {
    _hybrid('saveImage', { imageLink: options });
};

export const userInfo = () => {
    return new Promise(resolve => {
        _hybrid('userInfor', {}, function(data) {
            resolve(data);
        });
    });
};

/**
 * 支付
 * @param {*} options ，包含支付渠道和订单号
 */
export const router = (type, options) => {
    let params = Object.assign(
        {
            type: 'h5',
            animate: true,
            characterAllowed: true
        },
        options
    );
    console.log('开始路由跳转，参数：', params);
    _hybrid(type, params);
};
/**
 * 设置标题
 * @param {*} options
 */
export const header = options => {
    _hybrid('header', options);
};

/**
 * 支付
 * @param {*} options ，包含支付渠道和订单号
 */
export const pay = (options, callback) => {
    console.log('开始调用支付，参数：', options);
    return new Promise(function(resolve) {
        _hybrid(
            'pay',
            {
                orderNumber: options.orderNumber,
                orderType: options.orderType,
                payType: options.payType
            },
            res => {
                console.log('支付结果', res);
                if (res.isSuccess) {
                    resolve(true);
                } else {
                    resolve(false);
                }
            }
        );
    });
};
